package com.ttg.web.service.Impl;


import com.ttg.common.component.LoginCrypto;
import com.ttg.common.constant.BasicConstant;
import com.ttg.common.entities.UserTokenInfo;
import com.ttg.common.enums.AdminStatusEnum;
import com.ttg.common.enums.ErrorCodeEnums;
import com.ttg.common.exception.BaseException;
import com.ttg.common.utils.*;
import com.ttg.common.vo.VerificateVO;
import com.ttg.model.dto.ManageIndexReqDTO;
import com.ttg.model.pojo.Admin;
import com.ttg.model.vo.ManageIndexResVO;
import com.ttg.web.dao.AdminDao;
import com.ttg.web.redis.RedisConstants;
import com.ttg.web.redis.RedissonUtils;
import com.ttg.web.service.ManageRoleIndexService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RBucket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author zzq
 * @version 1.0
 * @Description
 * @date 2021/3/16 11:26
 */
@Slf4j
@Service
public class ManageIndexServiceImpl implements ManageRoleIndexService {
    @Autowired
    private RedissonUtils redissonUtils;
    @Autowired
    private AdminDao adminDao;

    @Override
    public ManageIndexResVO checkLogin(ManageIndexReqDTO reqDto) {
        if (StringUtils.isBlank(reqDto.getUserName())) {
            throw new BaseException(ErrorCodeEnums.USER_ACCOUNT_NOT_NULL);
        }
        if (StringUtils.isBlank(reqDto.getPassword())) {
            throw new BaseException(ErrorCodeEnums.USER_PASSWORD_NOT_NULL);
        }
        if (StringUtil.checkIllegalChar(reqDto.getUserName())) {
            throw new BaseException(ErrorCodeEnums.USER_ACCOUNT_NOT_NULL);
        }
        if (Objects.isNull(reqDto.getXWidth())) {
            throw new BaseException("验证码错误");
        }
        String userName = reqDto.getUserName();
        //验证码校验
        try {
            RBucket<Object> rBucket = redissonUtils.getRBucket(RedisConstants.MANAGE_USER_LOGIN_CODE + userName);
            if (Objects.isNull(rBucket) || Objects.isNull(rBucket.get())) {
                throw new BaseException("验证码错误,请刷新重试");
            }
            Integer width = (Integer) rBucket.getAndDelete();
            Integer xWidth = reqDto.getXWidth();
            if (Math.abs(width - xWidth) > BasicConstant.INT_5) {
                log.info("验证失败:width:{},xWidth:{}", width, xWidth);
                throw new BaseException("验证码验证失败");
            }
        } catch (BaseException e) {
            log.error("验证失败{}", e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("获取验证码失败{}", e.getMessage());
            throw new BaseException("获取验证码失败,请刷新重试:" + e.getMessage());
        }
        UserTokenInfo user = UserUtil.getUserThrow();
        if (StringUtils.isBlank(reqDto.getUserName())) {
            throw new BaseException(ErrorCodeEnums.USER_ACCOUNT_NOT_NULL);
        }
        if (StringUtils.isBlank(reqDto.getPassword())) {
            throw new BaseException(ErrorCodeEnums.USER_PASSWORD_NOT_NULL);
        }
        Admin admin = adminDao.findAdmByUserName(reqDto.getUserName());
        if (Objects.isNull(admin)) {
            throw new BaseException(ErrorCodeEnums.USER_NOT_EXIST);
        }
        if (!AdminStatusEnum.TYPE_1.getValue().equals(admin.getAdmStatus())) {
            throw new BaseException(ErrorCodeEnums.USER_ACCOUNT_LOCKED);
        }
        String password = reqDto.getPassword();
        if (!BasicUtils.MD5(password).equals(admin.getAdmPassword())) {
            Integer admErrTimes = admin.getAdmErrTimes();
            admErrTimes += 1;
            Admin up = new Admin();
            up.setAdmId(admin.getAdmId());

            if (admErrTimes < 10) {
                up.setAdmErrTimes(admErrTimes);
                adminDao.updateById(up);
                throw new BaseException(ErrorCodeEnums.PASSWORD_ERROR);
            }
            up.setAdmStatus(AdminStatusEnum.TYPE_2.getValue());
            adminDao.updateById(up);
            throw new BaseException(ErrorCodeEnums.USER_ACCOUNT_LOCKED);
        }
        Admin up = new Admin();
        up.setAdmId(admin.getAdmId());
        up.setAdmErrTimes(BasicConstant.INT_0);
        up.setAdmLastIp(user.getIp());
        up.setAdmLastTime(LocalDateTime.now());
        adminDao.updateById(up);
        ManageIndexResVO vo = new ManageIndexResVO();
        vo.setAdmUserName(admin.getAdmUserName());
        vo.setAdmId(admin.getAdmId().toString());
        try {
            // 获取 加密工具类
            LoginCrypto loginCrypto = JmSwitch.getLoginCrypto(user.getSign_type());
            vo.setAesKey(loginCrypto.genSymmetricKey());
            Map<String, String> info = new HashMap<>();
            String admId = vo.getAdmId();
            info.put(BasicConstant.MANAGE_JWT_KEY, admId);
            info.put(BasicConstant.MANAGE_JWT_AES_KEY, vo.getAesKey());
            //过期时间设为60分钟
            String token = JwtUtil.encode(info, RedisConstants.MANAGE_USER_LOGIN_T_CODE, BasicConstant.MANAGE_TOKEN_KEY, JwtUtil.getExpireDate(60));
            vo.setToken(token);
            log.info("token:{}", token);
            //aesKey存入redis
            RBucket<Object> rBucket = redissonUtils.getRBucket(RedisConstants.MANAGE_USER_LOGIN_T_CODE + admId);
            rBucket.set(vo.getAesKey(), BasicConstant.INT_1, TimeUnit.HOURS);
        } catch (Exception e) {
            log.error("登录失败:{}", e.getMessage());
            throw new BaseException("登录异常,请刷新重试:" + e.getMessage());
        }
        return vo;
    }

    @Override
    public VerificateVO loginCode(ManageIndexReqDTO reqDto) {
        if (StringUtils.isBlank(reqDto.getUserName())) {
            throw new BaseException(ErrorCodeEnums.USER_ACCOUNT_NOT_NULL);
        }
        VerificateVO vo = CaptchaUtil.getLoginCode();
        //存入缓存
        try {
            log.info("width:{}", vo.getXWidth());
            RBucket<Object> rBucket = redissonUtils.getRBucket(RedisConstants.MANAGE_USER_LOGIN_CODE + reqDto.getUserName());
            rBucket.set(vo.getXWidth(), 300, TimeUnit.SECONDS);
        } catch (Exception e) {
            log.error("redis 操作异常", e);
            throw new BaseException("获取验证码异常:" + e.getMessage());
        }

        // 移除横坐标送前端
        vo.setXWidth(null);
        return vo;
    }

    @Override
    public ManageIndexResVO logout() {
        UserTokenInfo user = UserUtil.getUserThrow();
        Long admId = user.getAdmId();
        if (Objects.isNull(admId)) {
            throw new BaseException("系统异常");
        }
        //删除redis缓存
        RBucket<Object> rBucket = redissonUtils.getRBucket(RedisConstants.MANAGE_USER_LOGIN_T_CODE + admId);
        rBucket.delete();
        ManageIndexResVO vo = new ManageIndexResVO();
        vo.setAdmId(StringUtil.toStringOrNull(admId));
        return vo;
    }


}
